package com.skyd.core.math;
/**
 * Math类的扩充
 * 
 * @author SkyD
 * 
 */
public final class MathEx {
	/**
	 * 根据勾股定理，计算两点间的距离长度
	 * 
	 * @param x1
	 *            坐标1的X值
	 * @param y1
	 *            坐标1的Y值
	 * @param x2
	 *            坐标2的X值
	 * @param y2
	 *            坐标2的Y值
	 * @return 两点间的直线距离长度
	 */
	public static double distance(double x1, double y1, double x2, double y2) {
		double dx = x2 - x1;
		double dy = y2 - y1;
		return Math.sqrt(dx * dx + dy * dy);
	}

	/**
	 * 将角度值转换为弧度
	 * 
	 * @param angle
	 *            一个0至360之间的值，表示角度
	 * @return 弧度值，一个0至2*PI之间的值
	 */
	public static double anglesToRadians(double angle) {
		return angle * (Math.PI / 180);
	}

	/**
	 * 将弧度值转换为角度
	 * 
	 * @param radian
	 *            一个0至2*PI之间的值，表示弧度
	 * @return 角度值，一个0至360之间的值
	 */
	public static double radiansToAngles(double radian) {
		return radian * (180 / Math.PI);
	}

	/**
	 * 接收角度值为参数的正弦函数
	 * 
	 * @param angle
	 *            一个0至360之间的值，表示角度
	 * @return 正弦值
	 */
	public static double sinAngle(double angle) {
		return Math.sin(anglesToRadians(angle));
	}

	/**
	 * 接收角度值为参数的余弦函数
	 * 
	 * @param angle
	 *            一个0至360之间的值，表示角度
	 * @return 余弦值
	 */
	public static double cosAngle(double angle) {
		return Math.cos(anglesToRadians(angle));
	}

	/**
	 * 接收角度值为参数的正切函数
	 * 
	 * @param angle
	 *            一个0至360之间的值，表示角度
	 * @return 正切值
	 */
	public static double tanAngle(double angle) {
		return Math.tan(anglesToRadians(angle));
	}

	/**
	 * 返回角度值的反正切函数
	 * 
	 * @param y
	 *            坐标Y值
	 * @param x
	 *            坐标X值
	 * @return 角度值，一个0至360之间的值
	 */
	public static double atan2Angle(double y, double x) {
		return radiansToAngles(Math.atan2(y, x));
	}
	
	/**
	 * 通过反正切计算两点间直线的倾斜角度
	 * 
	 * @param x1
	 *            坐标1的X值
	 * @param y1
	 *            坐标1的Y值
	 * @param x2
	 *            坐标2的X值
	 * @param y2
	 *            坐标2的Y值
	 * @return 角度值，一个0至360之间的值
	 */
	public static double angleOfLine(double x1, double y1, double x2, double y2) {
		return atan2Angle(y2-y1, x2-x1);
	}
	
	/**
	 * 返回角度值的反余弦函数
	 * @param ratio 余弦比例值，一个-1至1之间的值
	 * @return 角度值，一个0至360之间的值
	 */
	public static double acosAngle(double ratio)
	{
		return radiansToAngles(Math.acos(ratio));
	}
	
	/**
	 * 返回角度值的反正弦函数
	 * @param ratio 正弦比例值，一个-1至1之间的值
	 * @return 角度值，一个0至360之间的值
	 */
	public static double asinAngle(double ratio)
	{
		return radiansToAngles(Math.asin(ratio));
	}
	
	/**
	 * 角度标准化函数，修正角度值为0至360之间的值
	 * @param angle 待修正的角度值，一个0至360之间的值
	 * @return 角度值，一个0至360之间的值
	 */
	public static double fixAngle(double angle)
	{
		double a=angle%360;
		return a<0?a+360:a;
	}
	
	/**
	 * 根据勾股定理，计算两点间的距离长度
	 * 
	 * @param x1
	 *            坐标1的X值
	 * @param y1
	 *            坐标1的Y值
	 * @param x2
	 *            坐标2的X值
	 * @param y2
	 *            坐标2的Y值
	 * @return 两点间的直线距离长度
	 */
	public static float distance(float x1, float y1, float x2, float y2) {
		float dx = x2 - x1;
		float dy = y2 - y1;
		return (float) Math.sqrt(dx * dx + dy * dy);
	}

	/**
	 * 将角度值转换为弧度
	 * 
	 * @param angle
	 *            一个0至360之间的值，表示角度
	 * @return 弧度值，一个0至2*PI之间的值
	 */
	public static float anglesToRadians(float angle) {
		return (float) (angle * (Math.PI / 180));
	}

	/**
	 * 将弧度值转换为角度
	 * 
	 * @param radian
	 *            一个0至2*PI之间的值，表示弧度
	 * @return 角度值，一个0至360之间的值
	 */
	public static float radiansToAngles(float radian) {
		return (float) (radian * (180 / Math.PI));
	}

	/**
	 * 接收角度值为参数的正弦函数
	 * 
	 * @param angle
	 *            一个0至360之间的值，表示角度
	 * @return 正弦值
	 */
	public static float sinAngle(float angle) {
		return (float) Math.sin(anglesToRadians(angle));
	}

	/**
	 * 接收角度值为参数的余弦函数
	 * 
	 * @param angle
	 *            一个0至360之间的值，表示角度
	 * @return 余弦值
	 */
	public static float cosAngle(float angle) {
		return (float) Math.cos(anglesToRadians(angle));
	}

	/**
	 * 接收角度值为参数的正切函数
	 * 
	 * @param angle
	 *            一个0至360之间的值，表示角度
	 * @return 正切值
	 */
	public static float tanAngle(float angle) {
		return (float) Math.tan(anglesToRadians(angle));
	}

	/**
	 * 返回角度值的反正切函数
	 * 
	 * @param y
	 *            坐标Y值
	 * @param x
	 *            坐标X值
	 * @return 角度值，一个0至360之间的值
	 */
	public static float atan2Angle(float y, float x) {
		return (float) radiansToAngles(Math.atan2(y, x));
	}
	
	/**
	 * 通过反正切计算两点间直线的倾斜角度
	 * 
	 * @param x1
	 *            坐标1的X值
	 * @param y1
	 *            坐标1的Y值
	 * @param x2
	 *            坐标2的X值
	 * @param y2
	 *            坐标2的Y值
	 * @return 角度值，一个0至360之间的值
	 */
	public static float angleOfLine(float x1, float y1, float x2, float y2) {
		return atan2Angle(y2-y1, x2-x1);
	}
	
	/**
	 * 返回角度值的反余弦函数
	 * @param ratio 余弦比例值，一个-1至1之间的值
	 * @return 角度值，一个0至360之间的值
	 */
	public static float acosAngle(float ratio)
	{
		return (float) radiansToAngles(Math.acos(ratio));
	}
	
	/**
	 * 返回角度值的反正弦函数
	 * @param ratio 正弦比例值，一个-1至1之间的值
	 * @return 角度值，一个0至360之间的值
	 */
	public static float asinAngle(float ratio)
	{
		return (float) radiansToAngles(Math.asin(ratio));
	}
	
	/**
	 * 角度标准化函数，修正角度值为0至360之间的值
	 * @param angle 待修正的角度值，一个0至360之间的值
	 * @return 角度值，一个0至360之间的值
	 */
	public static float fixAngle(float angle)
	{
		float a=angle%360;
		return a<0?a+360:a;
	}
	
	/**
	 * 获取多个数中的最小值
	 */
	public static Long min(Long... values){
		Long m = Long.MAX_VALUE;
		for (Long f : values) {
			m=Math.min(m, f);
		}
		return m;
	}
	
	/**
	 * 获取多个数中的最大值
	 */
	public static Long max(Long... values){
		Long m = Long.MIN_VALUE;
		for (Long f : values) {
			m=Math.max(m, f);
		}
		return m;
	}
	
	/**
	 * 获取多个数中的最小值
	 */
	public static Integer min(Integer... values){
		Integer m = Integer.MAX_VALUE;
		for (Integer f : values) {
			m=Math.min(m, f);
		}
		return m;
	}
	
	/**
	 * 获取多个数中的最大值
	 */
	public static Integer max(Integer... values){
		Integer m = Integer.MIN_VALUE;
		for (Integer f : values) {
			m=Math.max(m, f);
		}
		return m;
	}
	
	/**
	 * 获取多个数中的最小值
	 */
	public static Float min(Float... values){
		Float m = Float.MAX_VALUE;
		for (Float f : values) {
			m=Math.min(m, f);
		}
		return m;
	}
	
	/**
	 * 获取多个数中的最大值
	 */
	public static Float max(Float... values){
		Float m = Float.MIN_VALUE;
		for (Float f : values) {
			m=Math.max(m, f);
		}
		return m;
	}
	
	/**
	 * 获取多个数中的最小值
	 */
	public static Double min(Double... values){
		Double m = Double.MAX_VALUE;
		for (Double f : values) {
			m=Math.min(m, f);
		}
		return m;
	}
	
	/**
	 * 获取多个数中的最大值
	 */
	public static Double max(Double... values){
		Double m = Double.MIN_VALUE;
		for (Double f : values) {
			m=Math.max(m, f);
		}
		return m;
	}
}
